using Basis;
using NL.Combat;
using NL.ControllerInteface;

using UnityEngine;


namespace NL.Advanced
{
    public interface ICombatManager
    {
        void OnOneLive(ICombatOwner who);
        void OnOneDead(ICombatOwner who);

        void OnOneLifing(ICombatOwner who, float hp, float max);

        bool GameRunning { get; }
    }
    public interface ICombatSub
    {
        void OnLive();
        void OnDead();

        void OnLifing(float hp, float max);

        void OnHurting(float hurt, ICombatOwner from);

        void OnHiting(float hit, ICombatOwner target);



        void OnOneLive(ICombatOwner who);
        void OnOneDead(ICombatOwner who);

        void OnOneLifing(ICombatOwner who, float hp, float max);

    }
    public interface ICombatOwner : ICampOwner, IBuffOwner, ILiving, IPropertyOwner, ITargetable, IObjStateOwner
    {
        long UDD { get; }
        short ObjType { get; }
        NLIni Info { get; }
        float HP { get; }

        float HPMax { get; }

        float HPPrecent { get; }

        public bool Moveable { get; }

        public bool Attackable { get; }
        public bool Skillable { get; }





        ATT GenarateAtt(PropertyCC _SkillProperty = null, AttackerInfo _AttProperty = default(AttackerInfo));
        DENF GenarateDefence();

        DENF GenarateDefence(AttackEffect Effect);
        void HealBy(HEAL heal, ICombatOwner combatOwner);
        void HitBy(HURT hurt, ICombatOwner combatOwner, GameObject launcher);

        void Hit(HURT hurt, ICombatOwner target, GameObject launcher);
    }
    public partial class CombatObj<P> : LivingOBJ, ICombatOwner, IInfoOwner where P : Property
    {
        NLIni IInfoOwner.Info => Info;

        IInfoOwner IInfoOwner.Set(NLIni _ini, bool _addi)
        {
            _Info = _ini;

            return this;
        }

        IInfoOwner IInfoOwner.Reset()
        {
            IInfoField[] componentsInChildren = GetComponentsInChildren<IInfoField>(includeInactive: true);
            if (componentsInChildren != null)
            {
                IInfoField[] array = componentsInChildren;
                foreach (IInfoField infoField in array)
                {
                    infoField.Reset(this);
                }
            }
            return this;
        }

        protected NLIni _Info;
        public NLIni Info => _Info;

        long ICombatOwner.UDD => UDD;
        short ICombatOwner.ObjType => ObjType;
        float ICombatOwner.HP => HP;
        float ICombatOwner.HPMax => HPMax;
        public float HPPrecent => HPMax <= 0 ? 1 : (1f * HP / HPMax);


        public virtual bool Moveable => !(this as IObjStateOwner).StateWith(ObjState.MoveNo);

        public virtual bool Attackable => !(this as IObjStateOwner).StateWith(ObjState.AttackNo);

        public virtual bool Skillable => !(this as IObjStateOwner).StateWith(ObjState.SkillNo);


        CampType ICampOwner.Camp => Camp;



        ATT ICombatOwner.GenarateAtt(PropertyCC _SkillProperty, AttackerInfo _AttProperty) => GenarateAtt(_SkillProperty, _AttProperty);


        DENF ICombatOwner.GenarateDefence() => GenarateDefence();

        DENF ICombatOwner.GenarateDefence(AttackEffect attackEffect) => GenarateDefence(attackEffect);

        void ICombatOwner.HealBy(HEAL heal, ICombatOwner from) => _DoHealBy(heal, from);


        void ICombatOwner.HitBy(HURT hurt, ICombatOwner from, GameObject launcher) => _DoHitBy(hurt, from, launcher);


        void ICombatOwner.Hit(HURT hurt, ICombatOwner target, GameObject launcher) => _DoHit(hurt, target, launcher);


        Property IPropertyOwner.GetProperty() => _Property;



        [Header("单位类型")]
        public short ObjType;

        [Header("初始化属性;阵营")]
        public string InitProperty = "";
        public CampType Camp = CampType.Team1;
        [Header("附加技能属性")]
        public string AddiProperty = "";


        [Header("受伤时候特效;治疗")]
        public GameObject Mod_Eff_Hurt;
        public bool UseHurtColorFlash = true;

        public GameObject Mod_Eff_Heal;


        [Header("受伤/治疗 数字显式")]
        public GameObject Mod_Hud_Hurt;
        public GameObject Mod_Hud_Heal;


        float _HPNow;

        public float HP
        {
            get => _HPNow;
            set
            {
                if (_HPNow != value)
                {
                    _CombataManager?.OnOneLifing(this, _HPNow, HPMax);

                    var all = GetComponentsInChildren<ICombatSub>();
                    foreach (var a in all)
                    {
                        a.OnLifing(_HPNow, HPMax);
                    }
                }

                _HPNow = value;

            }
        }

        public float _HPMax;

        public float HPMax
        {
            get => _HPMax;
            set
            {
                _HPMax = value;
            }
        }

        protected _MountController _MountCtrl;
        protected P _Property;


        string _OrginName;
        protected virtual void Awake()
        {
            _OrginName = name;
            _Property = gameObject.GETComponent<P>();

        }

        static long UDD_CLOCK = 30000;
        public long UDD;

        ICombatManager _CombataManager;

        public ICombatManager CombatManager => _CombataManager;
        protected override void OnLive()
        {
            base.OnLive();

            UDD = UDD_CLOCK++;
            name = $"{_OrginName}-{UDD}";
            _LoadInfo();



            _MountCtrl = gameObject.GETComponent<_MountController>();

            _MountCtrl?.Reset();

            _Property = gameObject.GETComponent<P>().Reset(InitProperty + NLConst.CHAR_ARRAY + AddiProperty) as P;

            OnProperty();

            _CombataManager=GetComponentInParent<ICombatManager>();


            _CombataManager?.OnOneLive(this);

            StateClean();
        }
        protected override void OnDead()
        {
            base.OnDead();

            GetComponentInParent<ICombatManager>()?.OnOneDead(this);

            StateClean();
        }

        protected virtual void _LoadInfo()
        {










        }
        protected virtual void OnProperty()
        {
            HPMax = HP = _Property["hp"];

        }
        protected virtual void _DoHealBy(HEAL heal, ICombatOwner from)
        {
            HP = Mathf.Min(HPMax, HP + heal.life);
        }
        protected virtual void _DoHitBy(HURT hurt, ICombatOwner from, GameObject launcher)
        {
            HP -= hurt.life;

            if (HP < 0)
            {
                DoKilled();
            }

            int dhp = (int)hurt.life;

            // 弹出受伤数字
            EFF.CreateEFF(Mod_Hud_Hurt, transform)?.TEXTSet(dhp.ToString(), true);
            //if (Mod_Hud_Heal!=null)
            //{
            //    var hud = BPoolMan.POOL["HUD"].Create(Mod_Hud_Heal);
            //    hud.transform.SETAs(transform);
            //    hud?.TEXTSet(((int)hurt.life).ToString());
            //}

            //受击特效.
            EFF.CreateEFF(Mod_Eff_Hurt, transform);

            //受击颜色
            if (UseHurtColorFlash)
            {
                gameObject.ONOFFSet(true, true, "HIT");
            }

            var all = GetComponentsInChildren<ICombatSub>();

            foreach (var a in all)
            {
                a.OnHurting(hurt.life, from);
            }
        }

        protected virtual void _DoHit(HURT hurt, ICombatOwner target, GameObject launcher)
        {
            var all = GetComponentsInChildren<ICombatSub>();

            foreach (var a in all)
            {
                a.OnHiting(hurt.life, target);
            }
        }


        protected void DoKilled()
        {

            _Dead();

            OnKilled();
        }

        protected void OnKilled()
        {

        }

        protected virtual ATT GenarateAtt(PropertyCC SkillProperty, AttackerInfo _AttProp)
        {
            if (_Property != null)
            {
                return new ATT()
                {
                    point = _Property["att"],
                    factor = 0,
                };
            }
            else
            {
                return default(ATT);
            }

        }

        protected virtual DENF GenarateDefence()
        {
            if (_Property != null)
            {
                return new DENF()
                {
                    denfence = _Property["denf"],

                };
            }
            else
            {
                return default(DENF);
            }
        }

        protected virtual DENF GenarateDefence(AttackEffect attEffect)
        {
            return GenarateDefence();
        }
    }
}

